
#include <BKeyEvent>
#include <BMouseEvent>
#include <BFocusEvent>
#include <BCamera>
#include <BViewer>
#include <BControl>
#include "member_BControl.h"

using namespace BWE;

#define member					(*(member_BControl*)_ptr)
#define member_allocate()		_ptr = new member_BControl(this)
#define member_release()		delete (member_BControl*)_ptr

BControl::BControl(const BString& name) : BObject(name)
{
	member_allocate();
}
BControl::~BControl()
{
	member_release();
}

BViewer* BControl::viewer() const
{
	return member.viewer;
}
BCamera* BControl::camera() const
{
	if (member.viewer)
		return member.viewer->camera();
	return 0;
}

void BControl::setMaster(BControl* master)
{
	if (member.master != master && master != this)
	{
		BHolder<BControl> holder;
		if (member.master)
		{
			holder = this;
			member.master->removeSlave(this);
		}
		if (master)
		{
			master->addSlave(this);
			holder = 0;
		}
	}
}
const BControl* BControl::master() const
{
	return member.master;
}
BControl* BControl::master()
{
	return member.master;
}

void BControl::addSlave(BControl* slave)
{
	if (slave && slave != this && !member.slaves.contain(slave))
	{
		member.slaves.append(slave);
		control_member(slave)->master = this;
		control_member(slave)->setViewer(member.viewer);
	}
}
void BControl::removeSlave(BControl* slave)
{
	if (slave && slave != this && member.slaves.contain(slave))
	{
		control_member(slave)->master = 0;
		control_member(slave)->setViewer(0);
		member.slaves.remove(slave);
	}
}
void BControl::clearSlaves()
{
	while (member.slaves.size())
	{
		BControl* slave = member.slaves.last();
		control_member(slave)->master = 0;
		control_member(slave)->setViewer(0);
		member.slaves.remove(slave);
	}
}

bool BControl::contains(BControl* slave)
{
	return member.slaves.contain(slave);
}
bool BControl::contains(const BString& name) const
{
	for (int i = 0; i < member.slaves.size(); i++)
	{
		if (member.slaves[i]->name() == name)
			return true;
	}
	return false;
}

int BControl::slaveCount() const
{
	return member.slaves.size();
}
BControl* BControl::slave(int index) const
{
	return member.slaves(index);
}
BControl* BControl::slave(const BString& name) const
{
	for (int i = 0; i < member.slaves.size(); i++)
	{
		if (member.slaves[i]->name() == name)
			return member.slaves[i];
	}
	return 0;
}

void BControl::setOrder(int order)
{
	if (member.master)
	{
		BArray<BControlHolder>& controls = control_member(member.master)->slaves;
		int pos = controls.indexOf(this);
		if (pos != order)
		{
			controls.swap(pos, order);
		}
	}
}
int BControl::order() const
{
	if (member.master)
	{
		BArray<BControlHolder>& controls = control_member(member.master)->slaves;
		return controls.indexOf(this);
	}
	return -1;
}

void BControl::raise()
{
	if (member.master && order() > 0)
	{
		BArray<BControlHolder>& controls = control_member(member.master)->slaves;
		int pos = controls.indexOf(this);
		controls.swap(pos, 0);

	}
}
void BControl::lower()
{
	if (member.master)
	{
		BArray<BControlHolder>& controls = control_member(member.master)->slaves;
		int pos = controls.indexOf(this);
		controls.swap(pos, controls.size() - 1);
	}
}

bool BControl::event(const BEvent& event)
{
	if(!member.viewer)
		return false;

	bool over = false;
	for (int i = 0; i < member.slaves.size(); i++)
	{
		if (!member.slaves[i]->able())
			continue;
		over |= member.slaves[i]->event(event);
		if (over)
			break;
	}

	if (over)
		return over;

	switch(event.type())
	{
	case Event_Update:
		this->updateEvent(event);
		break;
	case Event_Attach:
		this->attachEvent(event);
		break;
	case Event_Detach:
		this->detachEvent(event);
		break;
	case Event_Focus:
		over = this->focusEvent((const BFocusEvent&)event);
		break;
	case Event_KeyDown:
		over = this->keyDownEvent((const BKeyEvent&)event);
		break;
	case Event_KeyUp:
		over = this->keyUpEvent((const BKeyEvent&)event);
		break;
	case Event_MouseEnter:
		over = this->mouseEnterEvent((const BMouseEvent&)event);
		break;
	case Event_MouseLeave:
		over = this->mouseLeaveEvent((const BMouseEvent&)event);
		break;
	case Event_MouseMove:
		over = this->mouseMoveEvent((const BMouseEvent&)event);
		break;
	case Event_MousePress:
		over = this->mousePressEvent((const BMouseEvent&)event);
		break;
	case Event_MouseRelease:
		over = this->mouseReleaseEvent((const BMouseEvent&)event);
		break;
	case Event_MouseClick:
		over = this->mouseClickEvent((const BMouseEvent&)event);
		break;
	case Event_DoubleClick:
		over = this->mouseDoubleClickEvent((const BMouseEvent&)event);
		break;
	case Event_MouseWheel:
		over = this->mouseWheelEvent((const BMouseEvent&)event);
		break;
	case Event_DragEnter:
		over = this->dragEnterEvent((const BDragEvent&)event);
		break;
	case Event_DragLeave:
		over = this->dragLeaveEvent((const BDragEvent&)event);
		break;
	case Event_DragMove:
		over = this->dragMoveEvent((const BDragEvent&)event);
		break;
	case Event_DragDrop:
		over = this->dragDropEvent((const BDragEvent&)event);
		break;
	default:
		break;
	}

	return over;
}
void BControl::paint(BPainter& painter)
{

}
void BControl::render(BRender& render)
{

}

void BControl::updateEvent(const BEvent& event)
{

}

void BControl::attachEvent(const BEvent& event)
{

}
void BControl::detachEvent(const BEvent& event)
{

}

bool BControl::focusEvent(const BFocusEvent& event)
{
	return false;
}
bool BControl::keyDownEvent(const BKeyEvent& keyEvent)
{
	return false;
}
bool BControl::keyUpEvent(const BKeyEvent& keyEvent)
{
	return false;
}

bool BControl::mouseEnterEvent(const BMouseEvent& mouseEvent)
{
	return false;
}
bool BControl::mouseLeaveEvent(const BMouseEvent& mouseEvent)
{
	return false;
}

bool BControl::mousePressEvent(const BMouseEvent& mouseEvent)
{
	return false;
}
bool BControl::mouseReleaseEvent(const BMouseEvent& mouseEvent)
{
	return false;
}
bool BControl::mouseMoveEvent(const BMouseEvent& mouseEvent)
{
	return false;
}
bool BControl::mouseWheelEvent(const BMouseEvent& mouseEvent)
{
	return false;
}

bool BControl::mouseClickEvent(const BMouseEvent& mouseEvent)
{
	return false;
}
bool BControl::mouseDoubleClickEvent(const BMouseEvent& mouseEvent)
{
	return false;
}

bool BControl::dragEnterEvent(const BDragEvent& dragEvent)
{
	return false;
}
bool BControl::dragLeaveEvent(const BDragEvent& dragEvent)
{
	return false;
}
bool BControl::dragMoveEvent(const BDragEvent& dragEvent)
{
	return false;
}
bool BControl::dragDropEvent(const BDragEvent& dragEvent)
{
	return false;
}

